#include <bmpreader.h>

bmpreader::bmpreader(char *filename) :
	m_bmp()
{
	m_fp = fopen(filename, "rb");

	if (!m_fp)
	{
		printf("[bmpreader] - FATAL. Invalid filename: %s\n", filename);
		exit(1);
	}
}

bmpreader::~bmpreader()
{
	if (m_colors)
		delete[] m_colors;
	if (m_imageData)
		delete[] m_imageData;
}

BYTE * bmpreader::getImageData()
{
	return m_imageData;
}

void bmpreader::setImageData(BYTE *data, int size)
{
	memcpy(m_imageData, data, size);
}

int bmpreader::getWidth()
{
	return m_bmp.info.biWidth;
}

int bmpreader::getHeight()
{
	return m_bmp.info.biHeight;
}

void bmpreader::readBMP()
{
	readHeader();
	readInfoHeader();
	readColorTable();
	readImageData();
}

void bmpreader::writeBMP(char *filename)
{
	FILE *fp = fopen(filename, "w+");
	// header
	fwrite(&m_bmp.header.bfType, sizeof(WORD), 1, fp);
	fwrite(&m_bmp.header.bfSize, sizeof(DWORD), 1, fp);
	fwrite(&m_bmp.header.bfReserved1, sizeof(WORD), 1, fp);
	fwrite(&m_bmp.header.bfReserved2, sizeof(WORD), 1, fp);
	fwrite(&m_bmp.header.bfOffBits, sizeof(DWORD), 1, fp);

	// info header
	fwrite(&m_bmp.info.biSize, sizeof(DWORD), 1, fp);
	fwrite(&m_bmp.info.biWidth, sizeof(LONG), 1, fp);
	fwrite(&m_bmp.info.biHeight, sizeof(LONG), 1, fp);
	fwrite(&m_bmp.info.biPlanes, sizeof(WORD), 1, fp);
	fwrite(&m_bmp.info.biBitCount, sizeof(WORD), 1, fp);
	fwrite(&m_bmp.info.biCompression, sizeof(DWORD), 1, fp);
	fwrite(&m_bmp.info.biSizeImage, sizeof(DWORD), 1, fp);
	fwrite(&m_bmp.info.biXPelsPerMeter, sizeof(LONG), 1, fp);
	fwrite(&m_bmp.info.biYPelsPerMeter, sizeof(LONG), 1, fp);
	fwrite(&m_bmp.info.biClrUsed, sizeof(DWORD), 1, fp);
	fwrite(&m_bmp.info.biClrImportant, sizeof(DWORD), 1, fp);
   	
	// color table 
	int numColors= 1 << m_bmp.info.biBitCount;
	RGBQUAD* temp = m_colors;
	for (int i = 0; i < numColors; ++i)
	{
		fwrite(temp, sizeof(RGBQUAD), 1, fp);
		++temp;
	}

	// imagedata
    int size = m_bmp.header.bfSize - m_bmp.header.bfOffBits;
	fwrite(m_imageData, sizeof(BYTE), size, fp);	
}

void bmpreader::readHeader()
{
    fread(&m_bmp.header.bfType, sizeof(WORD), 1, m_fp);
    fread(&m_bmp.header.bfSize, sizeof(DWORD), 1, m_fp);
    fread(&m_bmp.header.bfReserved1, sizeof(WORD), 1, m_fp);
    fread(&m_bmp.header.bfReserved2, sizeof(WORD), 1, m_fp);
    fread(&m_bmp.header.bfOffBits, sizeof(DWORD), 1, m_fp);
}

void bmpreader::readInfoHeader()
{
    fread(&m_bmp.info.biSize, sizeof(DWORD), 1, m_fp);
    fread(&m_bmp.info.biWidth, sizeof(LONG), 1, m_fp);
    fread(&m_bmp.info.biHeight, sizeof(LONG), 1, m_fp);
    fread(&m_bmp.info.biPlanes, sizeof(WORD), 1, m_fp);
    fread(&m_bmp.info.biBitCount, sizeof(WORD), 1, m_fp);
    fread(&m_bmp.info.biCompression, sizeof(DWORD), 1, m_fp);
    fread(&m_bmp.info.biSizeImage, sizeof(DWORD), 1, m_fp);
    fread(&m_bmp.info.biXPelsPerMeter, sizeof(LONG), 1, m_fp);
    fread(&m_bmp.info.biYPelsPerMeter, sizeof(LONG), 1, m_fp);
    fread(&m_bmp.info.biClrUsed, sizeof(DWORD), 1, m_fp);
    fread(&m_bmp.info.biClrImportant, sizeof(DWORD), 1, m_fp);
}

void bmpreader::readColorTable()
{
    int numColors= 1 << m_bmp.info.biBitCount;
    RGBQUAD *start;

    //load the palette for 8 bits per pixel
    if(m_bmp.info.biBitCount == 8)
    {  
        m_colors= new RGBQUAD[numColors];
        start = m_colors;
        for (int i = 0; i < numColors; ++i)
        {  
            fread(m_colors,sizeof(RGBQUAD),1,m_fp);
            m_colors++;
        }
    }
    m_colors = start;
}

// pre-condition: readHeader() was succesfully read and m_m_fp points past the color table (if it exists)
void bmpreader::readImageData()
{
    int size = m_bmp.header.bfSize - m_bmp.header.bfOffBits;
    m_imageData = new BYTE[size];
    fread(m_imageData, sizeof(BYTE), size, m_fp);
}

void bmpreader::printHeader()
{
    printf("bfType: %x\n", m_bmp.header.bfType);
    printf("bfSize: %x\n", m_bmp.header.bfSize);
    printf("bfReserved1: %x\n", m_bmp.header.bfReserved1);
    printf("bfReserved2: %x\n", m_bmp.header.bfReserved2);
    printf("bfOffbits: %x\n", m_bmp.header.bfOffBits);
}

void bmpreader::printInfoHeader()
{
    printf("biSize: %x\n", m_bmp.info.biSize);
    printf("biWidth: %x\n", m_bmp.info.biWidth);
    printf("biHeight: %x\n", m_bmp.info.biHeight);
    printf("biPlanes: %x\n", m_bmp.info.biPlanes);
    printf("biBitCount: %x\n", m_bmp.info.biBitCount);
    printf("biCompression: %x\n", m_bmp.info.biCompression);
    printf("biSizeImage: %x\n", m_bmp.info.biSizeImage);
    printf("biXPelsPerMeter: %x\n", m_bmp.info.biXPelsPerMeter);
    printf("biYPelsPerMeter: %x\n", m_bmp.info.biYPelsPerMeter);
    printf("biClrUsed: %x\n", m_bmp.info.biClrUsed);
    printf("biClrImportant: %x\n", m_bmp.info.biClrImportant);
}

void bmpreader::printColorTable()
{

}

void bmpreader::printImageData()
{

}

